package com.yzc.android.manager;

import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.LinkedList;

import com.yzc.android.KDApp;
import com.yzc.android.beans.UpgradeVersionBean;
import com.yzc.android.utils.DownloadManagerPro;
import com.yzc.android.utils.PackageUtils;
import com.yzc.android.utils.PreferencesUtils;

/**
 * Created by yzc on 15/9/18.
 */
public enum UpgradeManager {
    INSTANCE;

    public static final String DOWNLOAD_FOLDER_NAME = "AndroidRapid";

    public static final String DOWNLOAD_FILE_NAME = "android_rapid.apk";

    public static final String KEY_UPGRADE_DOWNLOAD_ID = "UPGRADE_DOWNLOAD_ID";

    private static boolean isInitCalled = false;

    private Context mContext = KDApp.getInstance().getApplicationContext();

    private LinkedList<WeakReference<OnUpgradeListener>> mUpgradeListenerList = new LinkedList<>();

    private UpgradeVersionBean mUpgradeVersionBean;

    public final static int kDontUpgrade = 0;

    public final static int kIsForceUpgrade = 1;

    private boolean mIsAutoInstall = false;

    private DownloadManager mDownloadManager;

    private DownloadManagerPro mDownloadManagerPro;

    private long mDownloadId = 0;

    private MyHandler mHandler;

    private DownloadChangeObserver mDownloadChangeObserver;

    private CompleteReceiver mCompleteReceiver;

    public static synchronized UpgradeManager getInstance() {
        if (!isInitCalled)
        {
            INSTANCE.init();
            isInitCalled = true;
        }
        return INSTANCE;
    }

    private void init() {
        mHandler = new MyHandler();
        mDownloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        mDownloadManagerPro = new DownloadManagerPro(mDownloadManager);
        mDownloadChangeObserver = new DownloadChangeObserver();
        mCompleteReceiver = new CompleteReceiver();
        /** observer download change **/
        mContext.getContentResolver()
                .registerContentObserver(DownloadManagerPro.CONTENT_URI, true, mDownloadChangeObserver);
        mContext.registerReceiver(mCompleteReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }


    private void download(String url) {
        if (TextUtils.isEmpty(url))
            return;

        try {
            url = url.trim();
            String apkFilePath = new StringBuilder(Environment.getExternalStorageDirectory().getAbsolutePath()).append(
                    File.separator).append(DOWNLOAD_FOLDER_NAME).append(File.separator).toString();
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)).setAllowedNetworkTypes(
                    DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI)
                    .setVisibleInDownloadsUi(true)
                    .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                    .setTitle("AndroidRapid")
                    .setDestinationInExternalPublicDir(apkFilePath, DOWNLOAD_FILE_NAME)
                    .setMimeType("application/vnd.android.package-archive");
            mDownloadId = mDownloadManager.enqueue(request);
            for (WeakReference<OnUpgradeListener> listener : mUpgradeListenerList) {
                listener.get().onUpgradeDownloadStart(mUpgradeVersionBean);
            }
            /** save download id to preferences **/
            PreferencesUtils.putLong(mContext, KEY_UPGRADE_DOWNLOAD_ID, mDownloadId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void registerListener(final OnUpgradeListener listener) {
        WeakReference<OnUpgradeListener> weakListener = new WeakReference<>(listener);
        if (!mUpgradeListenerList.contains(weakListener))
        {
            mUpgradeListenerList.add(weakListener);
        }
    }

    public void unregisterListener(final OnUpgradeListener listener) {
        Iterator<WeakReference<OnUpgradeListener>> iterator = mUpgradeListenerList.iterator();
        while (iterator.hasNext()) {
            WeakReference<OnUpgradeListener> activityRef = iterator.next();
            if (activityRef.get() == null || activityRef.get() == listener) {
                iterator.remove();
            }
        }
    }


    /**
     * 检测版本，并显示相应 notify
     */
    public void handleVersionBean(UpgradeVersionBean bean) {
        if (bean == null) return;
        mUpgradeVersionBean = bean;
        String localVersion = KDApp.getInstance().getAppConfigManager().getAppVersion();
        String latestVersion = bean.latestVersion;
        if (bean.is_force > 0)
        {
            mIsAutoInstall = true;
            download(bean.packageUrl);
        }
        else if (checkNeedUpgrade(localVersion, latestVersion))
        {
            // 建议升级，弹出对话框让用户选择
            download(bean.packageUrl);
        }
    }

    private static boolean checkNeedUpgrade(String client, String server) {
        Log.e("client,server", client + "  " + server);
        boolean result = false;
        try {
            String[] ori = client.split("\\.");
            for (String temp : ori) {
                Log.e("temp", temp);
            }
            String[] tar = server.split("\\.");
            if (ori.length == 3) {
                client = client + ".0";
                ori = client.split("\\.");
            }
            if (tar.length == 3) {
                server = server + ".0";
                tar = server.split("\\.");
            }

            int len = tar.length;

            for (int i = 0; i < len; i++) {
                if (Integer.valueOf(ori[i]) > Integer.valueOf(tar[i])) {
                    return false;
                }
                if (Integer.valueOf(ori[i]) < Integer.valueOf(tar[i])) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return result;
    }

    class DownloadChangeObserver extends ContentObserver {

        public DownloadChangeObserver() {
            super(mHandler);
        }

        @Override
        public void onChange(boolean selfChange) {
            int[] bytesAndStatus = mDownloadManagerPro.getBytesAndStatus(mDownloadId);
            mHandler.sendMessage(mHandler.obtainMessage(0, bytesAndStatus[0], bytesAndStatus[1], bytesAndStatus[2]));
        }

    }

    class CompleteReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            /**
             * get the id of download which have download success, if the id is my id and it's status is successful,
             * then install it
             **/
            long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            mDownloadId = PreferencesUtils.getLong(context, KEY_UPGRADE_DOWNLOAD_ID);
            if (completeDownloadId == mDownloadId) {
                // if download successful, install apk
                // 下载成功
                for (WeakReference<OnUpgradeListener> listener : mUpgradeListenerList) {
                    listener.get().onUpgradeDownloadComplete(mUpgradeVersionBean);
                }

                if (mDownloadManagerPro.getStatusById(mDownloadId) == DownloadManager.STATUS_SUCCESSFUL && mIsAutoInstall) {
                    String apkFilePath = new StringBuilder(
                            Environment.getExternalStorageDirectory().getAbsolutePath()).append(File.separator)
                            .append(DOWNLOAD_FOLDER_NAME)
                            .append(File.separator)
                            .append(DOWNLOAD_FILE_NAME)
                            .toString();
                    PackageUtils.install(context, apkFilePath);
                }
            }
        }
    }

    /**
     * MyHandler
     *
     * @author Trinea 2012-12-18
     */
    private class MyHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case 0:
                    int status = (Integer) msg.obj;
                    if (status == DownloadManager.STATUS_RUNNING)
                    {
                        long progressSize = 0;
                        long maxSize = 0;
                        //downloadProgress.setVisibility(View.VISIBLE);
                        //downloadProgress.setMax(0);
                        //downloadProgress.setProgress(0);
                        //downloadButton.setVisibility(View.GONE);
                        //downloadSize.setVisibility(View.VISIBLE);
                        //downloadPrecent.setVisibility(View.VISIBLE);
                        //downloadCancel.setVisibility(View.VISIBLE);
                        if (msg.arg2 > 0)
                        {
                            progressSize = msg.arg1;
                            maxSize = msg.arg2;
                        }

                        //if (msg.arg2 < 0) {
                        //    //downloadProgress.setIndeterminate(true);
                        //    //downloadPrecent.setText("0%");
                        //    //downloadSize.setText("0M/0M");
                        //} else {
                        //    //downloadProgress.setIndeterminate(false);
                        //    //downloadProgress.setMax(msg.arg2);
                        //    //downloadProgress.setProgress(msg.arg1);
                        //    //downloadPrecent.setText(getNotiPercent(msg.arg1, msg.arg2));
                        //    //downloadSize.setText(getAppSize(msg.arg1) + "/" + getAppSize(msg.arg2));
                        //}
                        for (WeakReference<OnUpgradeListener> listener : mUpgradeListenerList) {
                            listener.get().onUpgradeDownloadProgress(mUpgradeVersionBean, progressSize, maxSize);
                        }
                    } else if (status == DownloadManager.STATUS_FAILED) {
                        // 下载失败
                        for (WeakReference<OnUpgradeListener> listener : mUpgradeListenerList) {
                            listener.get().onUpgradeDownloadFailed(mUpgradeVersionBean);
                        }
                    } else if (status == DownloadManager.STATUS_PAUSED){
                        // 下载暂停
                        for (WeakReference<OnUpgradeListener> listener : mUpgradeListenerList) {
                            listener.get().onUpgradeDownloadPause(mUpgradeVersionBean);
                        }
                    }
                    break;
            }
        }
    }

    static final DecimalFormat DOUBLE_DECIMAL_FORMAT = new DecimalFormat("0.##");

    public static final int MB_2_BYTE = 1024 * 1024;

    public static final int KB_2_BYTE = 1024;

    /**
     * @param size
     * @return
     */
    public static CharSequence getAppSize(long size) {
        if (size <= 0) {
            return "0M";
        }

        if (size >= MB_2_BYTE) {
            return new StringBuilder(16).append(DOUBLE_DECIMAL_FORMAT.format((double) size / MB_2_BYTE)).append("M");
        } else if (size >= KB_2_BYTE) {
            return new StringBuilder(16).append(DOUBLE_DECIMAL_FORMAT.format((double) size / KB_2_BYTE)).append("K");
        } else {
            return size + "B";
        }
    }

    public static String getNotiPercent(long progress, long max) {
        int rate = 0;
        if (progress <= 0 || max <= 0) {
            rate = 0;
        } else if (progress > max) {
            rate = 100;
        } else {
            rate = (int)((double)progress / max * 100);
        }
        return new StringBuilder(16).append(rate).append("%").toString();
    }

    public interface OnUpgradeListener
    {
        void onUpgradeDownloadStart(final UpgradeVersionBean versionBean);

        void onUpgradeDownloadPause(final UpgradeVersionBean versionBean);

        void onUpgradeDownloadComplete(final UpgradeVersionBean versionBean);

        void onUpgradeDownloadFailed(final UpgradeVersionBean versionBean);

        void onUpgradeDownloadProgress(final UpgradeVersionBean versionBean, final long progressSize, final long totalSize);

    }


}